﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Input;
using System.Drawing;
using OpenTK.Graphics;
using Common;

namespace T08.BasicShading {
    class MyGameWindow : GameWindow {
        public MyGameWindow() {
            this.Load += MyGameWindow_Load;
            this.Resize += MyGameWindow_Resize;
            this.RenderFrame += MyGameWindow_RenderFrame;
            this.Unload += MyGameWindow_Unload;
            this.Width = 1280;
            this.Height = 720;

        }


        private void MyGameWindow_RenderFrame(object sender, FrameEventArgs e) {
            GL.ClearColor(.1f, .1f, .99f, .9f);
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            Render();

            SwapBuffers();
            ProcessEvents();
        }

        Vao vao;
        Shader shader;
        int textureId;
        List<Vector3> vertexList = new List<Vector3>();
        List<Vector2> uvList = new List<Vector2>();
        List<Vector3> normalList = new List<Vector3>();
        Vector3[] vertices, normals;
        Vector2[] uvs;
        Vbo<Vector3> vertexBuffer, normalBuffer;
        Vbo<Vector2> uvBuffer;
        VertexAttribManager attribs = new VertexAttribManager();
        private void MyGameWindow_Load(object sender, EventArgs e) {

            VSync = VSyncMode.Off;
            GL.Enable(EnableCap.DepthTest);
            GL.DepthFunc(DepthFunction.Less);
            GL.Enable(EnableCap.CullFace);
            vao = new Vao();
            shader = new Shader("shader.vs", "shader.fs");

            textureId = DdsReader.LoadDds("uvmap.dds");
            ObjLoader.LoadObj("suzanne.obj", vertexList, uvList, normalList);
            vertices = vertexList.ToArray();
            uvs = uvList.ToArray();
            normals = normalList.ToArray();

            vertexBuffer = new Vbo<Vector3>(BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw, vertices);
            uvBuffer = new Vbo<Vector2>(BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw, uvs);
            normalBuffer = new Vbo<Vector3>(BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw, normals);

            attribs.AddAttrib(3, vertexBuffer);
            attribs.AddAttrib(2, uvBuffer);
            attribs.AddAttrib(3, normalBuffer);

        }

        private void Render() {
            shader.Use();
            InputControls.computeMatricesFromInput(this);
            var projection = InputControls.ProjectionMatrix;
            var view = InputControls.ViewMatrix;
            var model = Matrix4.Identity;
            var mvp = model * view * projection;

            shader.SetMatrix4("MVP", ref mvp);
            shader.SetMatrix4("M", ref model);
            shader.SetMatrix4("V", ref view);

            Vector3 lightPos = new Vector3(4, 4, 4);
            shader.SetVector3("LightPosition_worldspace", lightPos);

            GL.ActiveTexture(TextureUnit.Texture0);
            GL.BindTexture(TextureTarget.Texture2D, textureId);
            shader.SetInt("myTextureSampler", 0);

            attribs.Enable();
            GL.DrawArrays(PrimitiveType.Triangles, 0, this.vertices.Length);
            attribs.Disable();


        }

        private void MyGameWindow_Resize(object sender, EventArgs e) {
            GL.Viewport(0, 0, Width, Height);
        }



        private void MyGameWindow_Unload(object sender, EventArgs e) {
            shader.Dispose();
            vao.Dispose();
            vertexBuffer.Dispose();
            uvBuffer.Dispose();
            normalBuffer.Dispose();
        }

    }
}
